import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.Random;

public class Tank {
    int x, y, oldX, oldY;    
    public static final int XSPEED = 5;
    public static final int YSPEED = 5;
    public static final int WIDTH = 30;
    public static final int HEIGHT = 30;

    TankClient tc = null;
    private static Random r = new Random();
    Direction[] dirs = Direction.values();    
    private boolean live = true;
    private boolean bL = false, bU = false, bR = false, bD = false;
    private int life = 100;
    private boolean good;
    private BloodBar bb = new BloodBar();
    
    // Enum untuk arah gerakan tank
    public enum Direction {L, LU, U, RU, R, RD, D, LD, STOP}
    
    private Direction dir = Direction.D;
    // arah tank untuk menembak (tidak selalu sama dengan daemon movement)
    private Direction ptDir = Direction.D;    

    public int getX() { return x; }
    public int getY() { return y; }
    public boolean isGood() { return good; }
    public boolean isLive() { return live; }
    public int getLife() { return life; }
    
    public void setLive(boolean b) { this.live = b; }
    public void setLife(int life) { this.life = life; }
    
    public Tank(int x, int y) {
        this.x = x; 
        this.y = y;
    }
    
    public Tank(int x, int y, TankClient tc) {
        this(x, y);
        this.tc = tc;
    }
    
    public Tank(int x, int y, boolean good, TankClient tc) {
        this(x, y);
        this.tc = tc;
        this.good = good;
    }
    
    public void draw(Graphics g) {
        if (!live) return;
        
        // Jika tank pemain, gambarkan blood bar
        if (good) {
            bb.draw(g);
        }
        
        Color c = g.getColor();
        g.setColor(good ? Color.PINK : Color.CYAN);
        g.fillRect(x, y, WIDTH, HEIGHT);
        g.setColor(c);

        // Gambarkan arah tank (sebagai garis yang menunjukkan “meriam”)
        switch (ptDir) {
            case L:  g.drawLine(x + WIDTH/2, y + HEIGHT/2, x, y + HEIGHT/2); break;
            case LU: g.drawLine(x + WIDTH/2, y + HEIGHT/2, x, y); break;
            case U:  g.drawLine(x + WIDTH/2, y + HEIGHT/2, x + WIDTH/2, y); break;
            case RU: g.drawLine(x + WIDTH/2, y + HEIGHT/2, x + WIDTH, y); break;
            case R:  g.drawLine(x + WIDTH/2, y + HEIGHT/2, x + WIDTH, y + HEIGHT/2); break;
            case RD: g.drawLine(x + WIDTH/2, y + HEIGHT/2, x + WIDTH, y + HEIGHT); break;
            case D:  g.drawLine(x + WIDTH/2, y + HEIGHT/2, x + WIDTH/2, y + HEIGHT); break;
            case LD: g.drawLine(x + WIDTH/2, y + HEIGHT/2, x, y + HEIGHT); break;
            case STOP: break;
        }
        move(); 
    }
    
    // Menghasilkan boundary rectangle untuk collision detection
    public Rectangle getRect() {
        return new Rectangle(x, y, WIDTH, HEIGHT);
    }
    
    /**
     * Method untuk perpindahan posisi tank
     */
    void move() {
        // Simpan posisi lama
        oldX = x;
        oldY = y;

        // Jika bukan tank pemain, gerakan acak dan random fire
        if (!good) {
            if (r.nextInt(20) == 0) {
                // Update arah secara acak
                int rn = r.nextInt(dirs.length);
                dir = dirs[rn];
            }
            if (r.nextInt(40) > 38) {
                fire();
            }
        }
        
        // Gerakan sesuai arah
        switch (dir) {
            case L:  x -= XSPEED; break;
            case LU: x -= XSPEED; y -= YSPEED; break;
            case U:  y -= YSPEED; break;
            case RU: x += XSPEED; y -= YSPEED; break;
            case R:  x += XSPEED; break;
            case RD: x += XSPEED; y += YSPEED; break;
            case D:  y += YSPEED; break;
            case LD: x -= XSPEED; y += YSPEED; break;
            case STOP: break;
        }
        
        // Jika tank sedang bergerak, arah menembak mengikuti arah tank
        if (dir != Direction.STOP) {
            ptDir = dir;
        }
        
        // Validasi jika tank keluar area permainan
        if (x < 0) x = 0;
        if (y < 25) y = 25;
        if (x + WIDTH > TankClient.GAME_WIDTH) x = TankClient.GAME_WIDTH - WIDTH;
        if (y + HEIGHT > TankClient.GAME_HEIGHT) y = TankClient.GAME_HEIGHT - HEIGHT;
    }
    
    /**
     * Jika tank pemain menekan tombol keyboard
     */
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        switch (key) {
            case KeyEvent.VK_CONTROL: 
                fire(); 
                break;
            case KeyEvent.VK_LEFT:
                bL = true;
                break;
            case KeyEvent.VK_UP:
                bU = true;
                break;
            case KeyEvent.VK_RIGHT:
                bR = true;
                break;
            case KeyEvent.VK_DOWN:
                bD = true;
                break;
        }
        locateDirection();
    }
    
    /**
     * Jika tombol dilepas
     */
    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();
        switch (key) {
            case KeyEvent.VK_LEFT:
                bL = false;
                break;
            case KeyEvent.VK_UP:
                bU = false;
                break;
            case KeyEvent.VK_RIGHT:
                bR = false;
                break;
            case KeyEvent.VK_DOWN:
                bD = false;
                break;
            // Tombol A untuk tembakan "super" (menembak semua arah)
            case KeyEvent.VK_A:
                superFire();
                break;
        }
        locateDirection();
    }
    
    // Menentukan arah gerak berdasarkan tombol yang ditekan
    void locateDirection() {
        if (bL && !bU && !bR && !bD) dir = Direction.L;
        else if (bL && bU && !bR && !bD) dir = Direction.LU;
        else if (!bL && bU && !bR && !bD) dir = Direction.U;
        else if (!bL && bU && bR && !bD) dir = Direction.RU;
        else if (!bL && !bU && bR && !bD) dir = Direction.R;
        else if (!bL && !bU && bR && bD) dir = Direction.RD;
        else if (!bL && !bU && !bR && bD) dir = Direction.D;
        else if (bL && !bU && !bR && bD) dir = Direction.LD;
        else if (!bL && !bU && !bR && !bD) dir = Direction.STOP;
    }
    
    /**
     * Menembakkan peluru
     */
    public Missile fire() {
        if (!live) return null;
        int missileX = x + WIDTH / 2 - Missile.WIDTH / 2;
        int missileY = y + HEIGHT / 2 - Missile.HEIGHT / 2;
        Missile m = new Missile(missileX, missileY, ptDir, tc, good);
        tc.missiles.add(m);
        return m;
    }
    
    /**
     * Menembak dengan arah yang ditentukan
     */
    public Missile fire(Direction dir) {
        if (!live) return null;
        int missileX = x + WIDTH / 2 - Missile.WIDTH / 2;
        int missileY = y + HEIGHT / 2 - Missile.HEIGHT / 2;
        Missile m = new Missile(missileX, missileY, dir, tc, good);
        tc.missiles.add(m);
        return m;
    }
    
    /**
     * Tembakan spesial: menembak ke 8 arah sekaligus
     */
    public void superFire() {
        for (Direction d : Direction.values()) {
            if (d != Direction.STOP) { // Abaikan arah STOP
                fire(d);
            }
        }
    }
    
    /**
     * Method untuk mengambil bonus darah (blood) bila terjadi collision
     */
    public boolean eat(Blood b) {
        if (live && b.isLive() && this.getRect().intersects(b.getRect())) {
            this.life = 100;
            b.setLive(false);
            return true;
        }
        return false;
    }
    
    /**
     * Cek collision dengan dinding
     */
    public boolean collidesWithWall(Wall w) {
        if (live && this.getRect().intersects(w.getRect())) {
            stay();
            return true;
        }
        return false;
    }
    
    /**
     * Cek collision dengan tank lain
     */
    public boolean collidesWithTanks(java.util.List<Tank> tanks) {
        for (Tank t : tanks) {
            if (this != t && live && t.isLive() && this.getRect().intersects(t.getRect())) {
                t.stay();
                this.stay();
                return true;
            }
        }
        return false;
    }
    
    /**
     * Jika terjadi collision, kembalikan ke posisi lama
     */
    private void stay() {
        x = oldX;
        y = oldY;
    }
    
    /**
     * Inner class BloodBar untuk menggambar status darah tank
     */
    private class BloodBar {
        public void draw(Graphics g) {
            Color c = g.getColor();
            g.setColor(Color.RED);
            g.drawRect(x, y - 10, WIDTH, 10);
            int w = WIDTH * life / 100;
            g.fillRect(x, y - 10, w, 10);
            g.setColor(c);
        }
    }
}